<template>
  <div>
    <el-upload
      v-if="!isCheck"
      ref="upload"
      :multiple="multiple"
      :limit="limit"
      :before-upload="beforeUpload"
      :disabled="disabled"
      :accept="accept"
      :file-list="fileList"
      :headers="headers()"
      :action="action()"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :on-change="handleChange"
      :on-progress="handleProgress"
      :on-preview="handlePreview"
      :on-error="handleError"
    >
      <el-button type="primary" :disabled="disabled">{{ btnText }}</el-button>
      <div slot="tip" class="el-upload__tip mt0 pt10">{{ promptCaption }}</div>
    </el-upload>

    <!-- 文件查看 -->
    <div v-else>
      <div
        v-for="(item, index) in checkList"
        :key="index"
        class="fac file-list pl4 pr4 h26 pointer r4"
        @click="handlePreview(item)"
      >
        <i class="el-icon-document mr7"></i>
        <span class="ellipsis">{{ item.fileName }}</span>
      </div>
    </div>

    <!-- 图片查看 -->
    <image-viewer
      v-if="showImageViewer"
      :url-list="imgList"
      :initial-index="initialIndex"
      :onClose="imageViewerClose"
    />
  </div>
</template>

<script>
import util from "libs/util";
import { getPublicConfig } from "libs/getPublicConfig";
import getFileName from "libs/getFileName";
import emitter from "element-ui/src/mixins/emitter";
import ImageViewer from "components/image-viewer";
import IsImage from "is-image";

export default {
  components: { ImageViewer },
  mixins: [emitter],
  model: {
    prop: "value",
    event: "change",
  },
  props: {
    value: String,
    // 是否多选
    multiple: {
      type: Boolean,
      default: false,
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否为查看
    isCheck: {
      type: Boolean,
      default: false,
    },
    // 上传数量限制
    limit: {
      type: Number,
      default: 0,
    },
    // 文件大小
    size: {
      type: Number,
      default: 1,
    },
    // 文件大小单位
    unit: {
      type: String,
      default: "M",
    },
    // 接收的文件类型
    accept: {
      type: String,
      default: "*",
    },
    // 上传按钮显示的简介
    promptCaption: {
      type: String,
      default: "",
    },
    // 上传按钮文案
    btnText: {
      type: String,
      default: "点击上传",
    },
    // 请求头
    headers: {
      type: Function,
      default: () => {
        return {
          Authorization: util.cookies.get("token"),
          affiliationApp: getPublicConfig({
            key: "affiliationApp",
          }),
          affiliationAppType: getPublicConfig({
            key: "affiliationAppType",
          }),
        };
      },
    },
    // 上传接口拼接
    action: {
      type: Function,
      default: () => {
        let api = getPublicConfig({ key: "api" });
        // 兼容写法
        if (!api.endsWith("/")) api += "/";
        return `${api}sys/file/upload/inhandle`;
      },
    },
  },
  data() {
    return {
      fileList: [],
      // 图片查看器弹窗
      showImageViewer: false,
      // 默认展示的图片
      initialIndex: 0,
    };
  },
  computed: {
    // 文件中的图片列表
    imgList() {
      const fileArr = this.getFileList();
      let arr = [];
      // 只展示图片，其他的过滤掉(直接下载)
      fileArr.map((item) => {
        const { url } = item;
        IsImage(url) && arr.push(url);
      });
      return arr;
    },
    // 详情文件列表
    checkList() {
      let tempArr = [];
      this.fileList.map((item) => {
        const { url } = item;
        tempArr.push({ ...item, fileName: getFileName(url) });
      });
      return tempArr;
    },
  },
  watch: {
    value(newVal, oldVal) {
      if (!oldVal && newVal && !this.tempFlag) {
        this.fileList = this.getFileList();
      }
      this.dispatch("ElFormItem", "el.form.change", this.getFileStr(this.fileList));
    },
  },
  created() {
    if (this.value.length) {
      this.fileList = this.getFileList();
    }
  },
  methods: {
    /**
     * 获取文件列表
     */
    getFileList() {
      if (!this.value) return [];
      return this.value.split(",").map((item) => {
        return { name: getFileName(item), url: item };
      });
    },
    /**
     * 文件上传前的验证
     */
    beforeUpload(file) {
      let arr = [];
      if (this.value) {
        arr = this.value.split(",").map((item) => getFileName(item));
      }
      if (arr.includes(file.name)) {
        this.$message.error("请不要上传相同的文件");
        return false;
      }
      this.tempFlag = true;
      // 限制文件大小
      const { size } = file;
      let limitSizeBt = this.size * 1024;

      if (this.unit === "G") {
        limitSizeBt = limitSizeBt * 1024 * 1024;
      } else if (this.unit === "M") {
        limitSizeBt *= 1024;
      }
      if (limitSizeBt < size) {
        this.$message.error(`上传的文件大小不能超过${this.size}${this.unit}!`);
        return false;
      }
      return true;
    },
    /**
     * 获取文件列表
     */
    getFileStr(arr) {
      let tempArr = [];
      arr.map((item) => {
        const { response, url } = item;
        tempArr.push(url || response.data.savePath);
      });
      return tempArr.join(",");
    },
    /**
     * 文件超出个数限制时触发
     */
    handleExceed() {
      this.$message.error(`最多只能上传${this.limit}个文件`);
    },
    /**
     * 删除文件
     */
    handleRemove(file, fileList) {
      this.$emit("change", this.getFileStr(fileList));
    },
    /**
     * 文件上传成功
     */
    handleSuccess(response, file, fileList) {
      const { code, msg } = response;
      if (code === 401) {
        this.$message.error(msg);
        this.$router.replace({ name: "login" });
      } else if (code !== 200) {
        fileList.map((item) => {
          const { response } = item;
          if (response) {
            const { code } = response;
            if (code !== 200) {
              item.status = "fail";
            }
          }
        });
        // 删除上传失败的文件
        setTimeout(() => {
          fileList.splice(fileList.length - 1, 1);
        }, 1000);
        this.$message.error(msg);
      } else {
        this.$emit("change", this.getFileStr(fileList));
      }
    },
    /**
     * 文件状态改变时的钩子，
     * 添加文件、上传成功和上传失败时都会被调用
     */
    handleChange() {},
    /**
     * 文件上传失败
     */
    handleError() {},
    /**
     * 文件上传时
     */
    handleProgress() {},
    /**
     * 预览
     */
    handlePreview(file) {
      const url = file.url || file.response.data.savePath;
      if (!url) return;
      if (IsImage(url)) {
        // 是图片则查看
        this.initialIndex = this.imgList.findIndex((item) => item === url);
        this.showImageViewer = true;
      } else {
        // 非图片则下载
        location.href = url;
      }
    },
    /**
     * 关闭预览弹窗
     */
    imageViewerClose() {
      this.showImageViewer = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.file-list {
  transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
  &:not(:last-child) {
    margin-bottom: 5px;
  }
  i {
    color: #909399;
  }
  span {
    transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
    color: #606266;
  }
  &:hover {
    background-color: #f5f7fa;
    span {
      color: #409eff;
    }
  }
}

.el-upload__tip {
  line-height: 1;
}
</style>
